package com.xdjd.mobile.business.service;

import com.gitee.easyopen.exception.ApiException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xdjd.mobile.business.constant.*;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityClockAdditionalPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityClockDetailPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityClockSuperviseRecordPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityUserClockPoService;
import com.xdjd.mobile.business.dao.daoservice.member.MemberUserPoService;
import com.xdjd.mobile.business.dao.daoservice.member.MemberUserWalletPoService;
import com.xdjd.mobile.business.dao.mapper.activity.ActivityUserClockPoDao;
import com.xdjd.mobile.business.dao.mapper.member.MemberUserPoDao;
import com.xdjd.mobile.business.entity.model.activity.ActivityClockAdditionalPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityClockDetailPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityClockSuperviseRecordPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityUserClockPo;
import com.xdjd.mobile.business.entity.model.member.MemberUserPo;
import com.xdjd.mobile.business.entity.param.BasePageParam;
import com.xdjd.mobile.business.entity.param.clock.AddClockBonusParam;
import com.xdjd.mobile.business.entity.param.clock.BaseClockParam;
import com.xdjd.mobile.business.entity.param.clock.CreateClockParam;
import com.xdjd.mobile.business.entity.result.BasePageResult;
import com.xdjd.mobile.business.entity.result.alipay.AlipayTradeAppPayVo;
import com.xdjd.mobile.business.entity.result.clock.*;
import com.xdjd.mobile.business.entity.vo.ClockRecordListResult;
import com.xdjd.mobile.business.entity.vo.ClockRecordListVO;
import com.xdjd.mobile.business.entity.vo.LockListVO;
import com.xdjd.mobile.business.entity.vo.LockSuperviseListVO;
import com.xdjd.mobile.business.util.DateUtil;
import com.xdjd.mobile.business.util.UUIDUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2019/1/10 0010.
 */
@Service
public class ClockService {

    @Autowired
    private ActivityUserClockPoService activityUserClockPoService;
    @Autowired
    private ActivityClockDetailPoService activityClockDetailPoService;
    @Autowired
    private ActivityClockSuperviseRecordPoService activityClockSuperviseRecordPoService;
    @Autowired
    private MemberUserPoService memberUserPoService;
    @Autowired
    private ActivityUserClockPoDao activityUserClockPoDao;
    @Autowired
    private AliPayService aliPayService;
    @Autowired
    private MemberUserWalletPoService memberUserWalletPoService;
    @Autowired
    private MemberUserPoDao memberUserPoDao;
    @Autowired
    private ActivityClockAdditionalPoService activityClockAdditionalPoService;

    @Transactional
    public CreateClockResult createClock(CreateClockParam param, Long memberId) {
        CreateClockResult result = new CreateClockResult();
        List<ActivityUserClockPo> activityUserClockPos = activityUserClockPoService.checkClockingRecord(memberId);
        if (CollectionUtils.isNotEmpty(activityUserClockPos)) {
            throw new ApiException(ErrorCodeEnum.clock_repeat.getDesc(), ErrorCodeEnum.clock_repeat.getCode());
        }
        if (param.getBonus().longValue() <= 0) {
            throw new ApiException(ErrorCodeEnum.bonus_own.getDesc(), ErrorCodeEnum.bonus_own.getCode());
        }
        ActivityUserClockPo userClockPo = new ActivityUserClockPo();
        userClockPo.setMemberId(memberId);
        userClockPo.setClockNo("DK" + UUIDUtil.createOutTradeNo());
        userClockPo.setTradeType(param.getPayType());
        userClockPo.setOutTradeNo(UUIDUtil.createOutTradeNo());
        userClockPo.setDayStepNumber(param.getStepNumber());
        userClockPo.setDayNumber(param.getDayNumber());
        userClockPo.setOwnBonus(param.getBonus());
        userClockPo.setBonusPool(param.getBonus());
        userClockPo.setRemainDay(param.getDayNumber());
        //ToDo 对接支付之后状态先设置成0
        userClockPo.setStatus(ClockDBStatus.ongoing.getCode().byteValue());
        activityUserClockPoService.saveUserClock(userClockPo);
        this.createPay(memberId, param.getPayType(), userClockPo.getClockNo(), userClockPo.getOutTradeNo(), param.getBonus(), TradeType.add_clock_bonus.getCode().byteValue(), result);
        MemberUserPo userPo = memberUserPoService.getMemberById(memberId);
        result.setInviteCode(userPo.getInviteCode());
        return result;
    }

    @Transactional
    public AlipayTradeAppPayVo addClockBonus(AddClockBonusParam param, Long memberId) {
        AlipayTradeAppPayVo vo = new AlipayTradeAppPayVo();
        if (param.getBonus().longValue() <= 0) {
            throw new ApiException(ErrorCodeEnum.bonus_add.getDesc(), ErrorCodeEnum.bonus_add.getCode());
        }
        String outTradeNo = UUIDUtil.createOutTradeNo();
        this.createPay(memberId, param.getPayType(), param.getClockNo(), outTradeNo, param.getBonus(), TradeType.add_clock_bonus.getCode().byteValue(), vo);
        ActivityClockAdditionalPo additionalPo = new ActivityClockAdditionalPo();
        additionalPo.setAdditionalBonus(param.getBonus());
        additionalPo.setClockNo(param.getClockNo());
        additionalPo.setMemberId(memberId);
        additionalPo.setOutTradeNo(outTradeNo);
        additionalPo.setTradeType(param.getPayType());
        additionalPo.setStatus(PayResultStatus.is_pay.getCode().byteValue());
        activityClockAdditionalPoService.saveClockAdditional(additionalPo);
        //Todo 增加奖金池在微信或者支付宝回调中增加
        int i = activityClockSuperviseRecordPoService.addClockBonus(memberId, param.getClockNo(), param.getBonus());
        if (i > 0) {
            int addBonusPool = activityUserClockPoService.addBonusPool(param.getClockNo(), param.getBonus());
            if (addBonusPool > 0) {
                return vo;
            } else {
                throw new ApiException(ErrorCodeEnum.bonus_add_error.getDesc(), ErrorCodeEnum.bonus_add_error.getCode());
            }
        } else {
            throw new ApiException(ErrorCodeEnum.bonus_add_error.getDesc(), ErrorCodeEnum.bonus_add_error.getCode());
        }
    }

    private void createPay(Long memberId, Byte payType, String clockNo, String outTradeNo, Long bonus, Byte payStatus, AlipayTradeAppPayVo vo) {
        if (0 == payType.intValue()) {
            //支付宝
//            AlipayCreateParam alipayCreateParam = new AlipayCreateParam();
//            alipayCreateParam.setRecordNo(clockNo);
//            alipayCreateParam.setOutTradeNo(outTradeNo);
//            alipayCreateParam.setPayType(payStatus);
//            alipayCreateParam.setPayAmount(bonus);
//            vo = aliPayService.createAliPayReq(alipayCreateParam);
            vo.setBody("free");
        } else if (1 == payType.intValue()) {
            //微信
            vo.setBody("free");
        } else if (2 == payType.intValue()) {
            //余额
            int i1 = memberUserWalletPoService.reduceBalance(memberId, bonus);
            if (i1 <= 0) {
                throw new ApiException(ErrorCodeEnum.balance_not_enough.getDesc(), ErrorCodeEnum.balance_not_enough.getCode());
            }
        } else {
            throw new ApiException(ErrorCodeEnum.not_pay_type.getDesc(), ErrorCodeEnum.not_pay_type.getCode());
        }
    }

    public CheckClockRecordResult clockDetail(String clockNo) {
        CheckClockRecordResult recordResult = new CheckClockRecordResult();
        ActivityUserClockPo userClockPo = activityUserClockPoService.findByClockNo(clockNo);
        this.transClockRecord(userClockPo, recordResult);
        return recordResult;

    }

    private Integer remainDayConvertCurday(Integer curDay, Integer totalDay) {
        curDay = curDay == null ? 0 : curDay;
        totalDay = totalDay == null ? 0 : totalDay;
        return totalDay - curDay;
    }

    public BasePageResult<LockSuperviseListVO> lockSuperviseList(Long id, BasePageParam param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        List<LockSuperviseListVO> lockSuperviseListVOS = activityUserClockPoDao.lockSuperviseList(id, DateUtil.getDate(new Date()));
        PageInfo pageInfo = new PageInfo(lockSuperviseListVOS);
        return new BasePageResult<>(pageInfo.getTotal(), lockSuperviseListVOS);
    }

    public BasePageResult<LockListVO> lockList(Long id, BasePageParam param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        List<LockListVO> lockListVOS = activityUserClockPoDao.lockList(id);
        PageInfo pageInfo = new PageInfo(lockListVOS);
        if (CollectionUtils.isNotEmpty(lockListVOS)) {
            for (LockListVO lockListVO : lockListVOS) {
                lockListVO.setCurDay(remainDayConvertCurday(lockListVO.getCurDay(), lockListVO.getTotalDay()));
            }
        }
        return new BasePageResult<>(pageInfo.getTotal(), lockListVOS);
    }

    public net.oschina.durcframework.easymybatis.PageInfo<ClockRecordResult> getClockRecordList(BasePageParam param, Long memberId) {
        net.oschina.durcframework.easymybatis.PageInfo<ActivityUserClockPo> recordPage = activityUserClockPoService.getAllValid(memberId, param.getPageIndex(), param.getPageSize());
        net.oschina.durcframework.easymybatis.PageInfo<ClockRecordResult> pageInfo = new net.oschina.durcframework.easymybatis.PageInfo<>();
        List<ClockRecordResult> resultList = new ArrayList<>();
        List<ActivityUserClockPo> list = recordPage.getList();
        for (ActivityUserClockPo detailPo : list) {
            ClockRecordResult result = new ClockRecordResult();
            result.setTargetStepNumber(detailPo.getDayStepNumber());
            result.setEntryPrice(detailPo.getEntryPrice());
            result.setClockNo(detailPo.getClockNo());
            String startDate = DateUtil.getDate(DateUtil.addDay(detailPo.getCreateTime(), 1));
            String endDate = DateUtil.getDate(DateUtil.addDay(detailPo.getCreateTime(), detailPo.getDayNumber()));
            result.setTimeRange(startDate + "到" + endDate);
            List<ActivityClockSuperviseRecordPo> recordPos = activityClockSuperviseRecordPoService.findByClockNo(detailPo.getClockNo());
            List<SuperviseVo> memberList = new ArrayList<>();
            for (ActivityClockSuperviseRecordPo recordPo : recordPos) {
                SuperviseVo vo = new SuperviseVo();
                MemberUserPo userPo = memberUserPoService.getMemberById(recordPo.getMemberId());
                vo.setLogo(userPo.getImage());
                memberList.add(vo);
            }
            result.setList(memberList);
            if (detailPo.getStatus().intValue() == ClockDBStatus.ongoing.getCode().intValue()) {
                result.setStatus(ClockAndChallengeResultStatus.ongoing.getCode().byteValue());
            } else {
                if (detailPo.getCompleteStatus().intValue() == ClockCompleteStatus.failure.getCode().intValue()) {
                    result.setStatus(ClockAndChallengeResultStatus.failure.getCode().byteValue());
                } else {
                    result.setStatus(ClockAndChallengeResultStatus.successful.getCode().byteValue());
                }
            }
            resultList.add(result);
        }
        pageInfo.setList(resultList);
        pageInfo.setPageIndex(recordPage.getPageIndex());
        pageInfo.setPageSize(recordPage.getPageSize());
        pageInfo.setTotal(recordPage.getTotal());
        return pageInfo;
    }

    public CheckBaseResult checkClockRecord(Long memberId) {
        CheckBaseResult recordResult = new CheckBaseResult();
        ActivityUserClockPo userClockPo = activityUserClockPoService.findByMemberId(memberId);
        if (userClockPo == null) {
            recordResult.setExistStatus(ExistClockStatus.not_exist.getCode().byteValue());
            return recordResult;
        }
        recordResult.setExistStatus(ExistClockStatus.exist.getCode().byteValue());
        this.transClockRecord(userClockPo, recordResult);
        recordResult.setClockNo(userClockPo.getClockNo());
        return recordResult;
    }

    private void transClockRecord(ActivityUserClockPo userClockPo, CheckClockRecordResult recordResult) {
        recordResult.setBonusPool(userClockPo.getBonusPool());
        recordResult.setCurDay(remainDayConvertCurday(userClockPo.getRemainDay(), userClockPo.getDayNumber()));
        recordResult.setTotalDay(userClockPo.getDayNumber());
        recordResult.setTotalStep(userClockPo.getDayStepNumber());
        ActivityClockDetailPo clockDetailPo = activityClockDetailPoService.findByClockNoAndDate(userClockPo.getClockNo(), DateUtil.getDate(new Date()));
        if (clockDetailPo == null) {
            recordResult.setCurStep(0l);
        } else {
            recordResult.setCurStep(clockDetailPo.getTodayStepNumber());
        }
    }

    public ClockRecordListResult clockRecordList(String clockNo) {

        ActivityUserClockPo activityUserClockPo = activityUserClockPoDao.getByProperty("clock_no", clockNo);
        if (activityUserClockPo == null) {
            throw new ApiException("打卡数据不存在");
        }
        Integer curDay = remainDayConvertCurday(activityUserClockPo.getRemainDay(), activityUserClockPo.getDayNumber());
        MemberUserPo memberUserPo = memberUserPoDao.getByProperty("id", activityUserClockPo.getMemberId());
        if (memberUserPo == null) {
            throw new ApiException("用户不存在");
        }
        ClockRecordListResult clockRecordListResult = new ClockRecordListResult();
        Long targetStep = activityUserClockPo.getDayStepNumber();
        clockRecordListResult.setDayStep(targetStep);
        clockRecordListResult.setNickName(memberUserPo.getNickName());
        clockRecordListResult.setImage(memberUserPo.getImage());
        clockRecordListResult.setSignature(memberUserPo.getSignature());
        List<Integer> curDays = getCurDays(curDay);
        List<ClockRecordListVO> clockRecordListVOS = activityUserClockPoDao.clockRecordList(clockNo, curDays);
        if (CollectionUtils.isNotEmpty(clockRecordListVOS)) {
            Long step;
            for (ClockRecordListVO clockRecordListVO : clockRecordListVOS) {
                step = clockRecordListVO.getStep() == null ? 0 : clockRecordListVO.getStep();
                clockRecordListVO.setStep(step);
                if (step >= targetStep) {
                    clockRecordListVO.setStatus(1);
                } else {
                    clockRecordListVO.setStatus(0);
                }
            }
        }
        clockRecordListResult.setClockRecordListVOList(clockRecordListVOS);
        return clockRecordListResult;
    }

    private List<Integer> getCurDays(Integer curDay) {
        List<Integer> list = new ArrayList<>();
        for (int i = 1; i < curDay; i++) {
            list.add(i * (-1));
        }
        return list;

    }


}
